package com.apache.log.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apache.api.vo.ParamsVo;
import com.apache.audit.entity.LogModel;
import com.apache.audit.entity.LogModelDetail;
import com.apache.audit.entity.LogOperation;
import com.apache.cache.util.Validator;
import com.apache.database.model.Page;
import com.apache.exception.BusinessException;
import com.apache.log.common.PropertiesConfig;
import com.apache.log.es.ESBaseDao;
import com.apache.log.es.config.IndexConfig;
import com.apache.log.manager.LogManager;
import com.apache.tools.DateUtils;
import com.apache.tools.StrUtil;
import com.apache.tools.UUIDUtil;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description:
 * @author: Hou Dayu
 * @date: Created in 2020/11/18
 */
public class ESManagerImpl implements LogManager {

    private ESBaseDao esBaseDao;
    private IndexConfig indexConfig = new IndexConfig();;

    public ESManagerImpl(ESBaseDao esBaseDao){
        this.esBaseDao = esBaseDao;
    }

    @Override
    public String saveInfo(ParamsVo vo) throws BusinessException {
        String infoId = UUIDUtil.getPrimaryKey();
        String indexName = null;
        String indexType = "doc";
        Map<String,Object> data = new HashMap();
        if(vo.getObj() instanceof LogModel){
            LogModel logModel = (LogModel)vo.getObj();
            logModel.setModelId(infoId);
            indexName = PropertiesConfig.MODEL_INDEX;
            data = (Map)JSON.toJSON(logModel);
        } else if(vo.getObj() instanceof LogModelDetail){
            LogModelDetail detail = (LogModelDetail)vo.getObj();
            detail.setDetailId(infoId);
            indexName = PropertiesConfig.MODEL_DETAIL_INDEX;
            data = (Map)JSON.toJSON(detail);
        } else {
            LogOperation operation = (LogOperation)vo.getObj();
            operation.setLogId(infoId);
            LogModel logModel = (LogModel)vo.getParams("LogModel");
            data.put("LogModel",vo.getParams("LogModel"));
            JSONObject json = (JSONObject)JSON.toJSON(operation);
            json.put("modelCname",logModel.getModelCname());
            json.put("modelBussiness",logModel.getModelBussiness());
            json.put("modelSysname",logModel.getModelSysname());
            json.put("details",JSON.toJSONString(vo.getObjs()));
            data = (Map)json;
            indexName = PropertiesConfig.OPERATION_INDEX+"-"+ DateUtils.Now.fmt_yyyy();
            if(!esBaseDao.indexExists(indexName)){
                esBaseDao.createIndex(indexName,"doc",indexConfig.getSettings(PropertiesConfig.OPERATION_INDEX),indexConfig.getMappings(PropertiesConfig.OPERATION_INDEX));
            }
        }
        esBaseDao.createIndexInfo(indexName,indexType,infoId,data);
        return infoId;
    }

    @Override
    public boolean editInfo(ParamsVo vo) throws BusinessException {
        Map<String,Object> data = new HashMap();
        String indexName=null;
        String indexType="doc";
        String infoId = null;
        if(vo.getObj() instanceof LogModel){
            LogModel logModel = (LogModel)vo.getObj();
            if(StrUtil.isNotNull(logModel.getModelId())) {
                infoId = logModel.getModelId();
                indexName = PropertiesConfig.MODEL_INDEX;
                data = (Map)JSON.toJSON(logModel);
            }
        } else if(vo.getObj() instanceof LogModelDetail){
            LogModelDetail detail = (LogModelDetail)vo.getObj();
            if(StrUtil.isNotNull(detail.getDetailId())) {
                infoId = detail.getDetailId();
                indexName = PropertiesConfig.MODEL_DETAIL_INDEX;
                data = (Map)JSON.toJSON(detail);
            }
        }
        return esBaseDao.updateIndexInfo(indexName,indexType,infoId,data);
    }

    @Override
    public boolean deleteInfo(ParamsVo vo) throws BusinessException {
        String infoId = vo.getInfoId();
        if (Validator.isNull(infoId)) {
            return false;
        }
        String indexName=null;
        if(vo.getObj() instanceof LogModel){
            indexName = PropertiesConfig.MODEL_INDEX;
        } else if(vo.getObj() instanceof LogModelDetail){
            indexName = PropertiesConfig.MODEL_DETAIL_INDEX;
        }
        return esBaseDao.delIndexInfo(indexName,infoId);
    }

    @Override
    public Object getInfoById(ParamsVo vo) {
        String infoId = vo.getInfoId();
        if (Validator.isNull(infoId)) {
            return false;
        }
        String indexName=null;
        if(vo.getObj() instanceof LogModel){
            indexName = PropertiesConfig.MODEL_INDEX;
        } else if(vo.getObj() instanceof LogModelDetail){
            indexName = PropertiesConfig.MODEL_DETAIL_INDEX;
        } else if(vo.getObj() instanceof LogOperation){
            indexName = PropertiesConfig.OPERATION_INDEX;
        }
        return esBaseDao.selectById(indexName,infoId);
    }

    @Override
    public List getList(ParamsVo vo) {
        int pageSize = 100;
        int pageIndex =1;
        JSONObject boolQuery = new JSONObject();
        String str = setMethodParams(vo.getObj(),vo.getParams());
        if(StrUtil.isNotNull(str)){
            boolQuery.put("bool",getValue("filter",JSON.parse(str)));
        }
        SortBuilder sortBuilder = (SortBuilder)vo.getParams("orderBy");
        String indexName = vo.getParamsToStr("indexName");
        Page page = esBaseDao.pageList(indexName,"doc",pageIndex,pageSize,boolQuery.toJSONString(),sortBuilder);
        return page.getPageObjects();
    }

    @Override
    public Page getPageInfo(ParamsVo vo) {
        int pageSize = Integer.valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageSize")), "10"));
        int pageIndex = Integer.valueOf(Validator.getDefaultStr(String.valueOf(vo.getParams("pageIndex")), "1"));
        JSONObject boolQuery = new JSONObject();
        String str = setMethodParams(vo.getObj(),vo.getParams());
        if(StrUtil.isNotNull(str)){
            boolQuery.put("bool","{\"filter\":"+str+"}");
        }
        SortBuilder sortBuilder = (SortBuilder)vo.getParams("orderBy");
        String indexName = vo.getParamsToStr("indexName");
        return esBaseDao.pageList(indexName,"doc",pageIndex,pageSize,boolQuery.toJSONString(),sortBuilder);
    }

    private String setMethodParams(Object obj,Map<String,Object> params){
        JSONArray json = new JSONArray();
        SortBuilder sortBuilder = null;
        if(obj instanceof LogModel){
            if (!Validator.isEmpty(obj)) {
                LogModel logModel = (LogModel)obj;
                if (Validator.isNotNull(logModel.getModelCname())) {
                    json.add(getValue("wildcard",getValue("modelCname","*"+logModel.getModelCname()+"*")));
                }
                if (Validator.isNotNull(logModel.getModelEname())) {
                    json.add(getValue("term",getValue("modelEname",logModel.getModelEname())));
                }
                if (Validator.isNotNull(logModel.getModelBussiness())) {
                    json.add(getValue("term",getValue("modelBussiness",logModel.getModelBussiness())));
                }
                if (Validator.isNotNull(logModel.getModelSysname())) {
                    json.add(getValue("term",getValue("modelSysname",logModel.getModelSysname())));
                }
            }
            sortBuilder = SortBuilders.fieldSort("modelEname");
            sortBuilder.order(SortOrder.DESC);
            params.put("orderBy",sortBuilder);
            params.put("indexName",PropertiesConfig.MODEL_INDEX);
        } else if(obj instanceof LogModelDetail){
            if (!Validator.isEmpty(obj)) {
                LogModelDetail logModelDetail = (LogModelDetail)obj;
                if (Validator.isNotNull(logModelDetail.getModelId())) {
                    json.add(getValue("term",getValue("modelId",logModelDetail.getModelId())));
                }
                if (Validator.isNotNull(logModelDetail.getColumnCname())) {
                    json.add(getValue("wildcard",getValue("columnCname","*"+logModelDetail.getColumnCname()+"*")));
                }
                if (Validator.isNotNull(logModelDetail.getColumnEname())) {
                    json.add(getValue("term",getValue("columnCname",logModelDetail.getColumnEname())));
                }
            }
            sortBuilder = SortBuilders.fieldSort("columnEname");
            sortBuilder.order(SortOrder.DESC);
            params.put("orderBy",sortBuilder);
            params.put("indexName",PropertiesConfig.MODEL_DETAIL_INDEX);
        } else if(obj instanceof LogOperation){
            if (!Validator.isEmpty(obj)) {
                LogOperation logOperation = (LogOperation)obj;
                if (Validator.isNotNull(logOperation.getModelId())) {
                    json.add(getValue("term",getValue("modelId",logOperation.getModelId())));
                }
                if (Validator.isNotNull(logOperation.getLogType())) {
                    json.add(getValue("term",getValue("logType",logOperation.getLogType())));
                }
                if (Validator.isNotNull(logOperation.getCreateUser())) {
                    json.add(getValue("term",getValue("createUser",logOperation.getCreateUser())));
                }
                if (Validator.isNotNull(logOperation.getLogIp())) {
                    json.add(getValue("term",getValue("logIp",logOperation.getLogIp())));
                }
                if (Validator.isNotNull(logOperation.getPrimaryKey())) {
                    json.add(getValue("term",getValue("primaryKey",logOperation.getPrimaryKey())));
                }
                String modelSysname = String.valueOf(params.get("modelSysname"));
                String modelBussiness = String.valueOf(params.get("modelBussiness"));
                String modelCname = String.valueOf(params.get("modelCname"));
                String createdTime = String.valueOf(params.get("createdTime"));
                if (Validator.isNotNull(modelSysname)) {
                    json.add(getValue("term",getValue("modelSysname",modelSysname)));
                }
                if (Validator.isNotNull(modelBussiness)) {
                    json.add(getValue("term",getValue("modelBussiness",modelBussiness)));
                }
                if (Validator.isNotNull(modelCname)) {
                    json.add(getValue("wildcard",getValue("modelCname","*"+modelCname+"*")));
                }
                if (Validator.isNotNull(createdTime)) {
                    long startTime = DateUtils.strToLong(createdTime + " 00:00:00", DateUtils.FmtStr.yyyyMMdd_HHmmss);
                    long stopTime = DateUtils.strToLong(createdTime + " 23:59:59", DateUtils.FmtStr.yyyyMMdd_HHmmss);
                    JSONObject gte = new JSONObject();
                    gte.put("from", startTime);
                    gte.put("to", stopTime);
                    json.add(getValue("range",getValue("createdTime",gte)));
                }
            }
            sortBuilder = SortBuilders.fieldSort("createdTime");
            sortBuilder.order(SortOrder.DESC);
            params.put("orderBy",sortBuilder);
            params.put("indexName",PropertiesConfig.OPERATION_INDEX);
        }
        return json.toJSONString();
    }

    private JSONObject getValue(String key,Object val){
        JSONObject json = new JSONObject();
        json.put(key,val);
        return json;
    }
}
